package javaDemo.jvm.day_02_02_JMM;

import lombok.Data;

import java.util.concurrent.TimeUnit;

/**
 * @Description TODO 自己理解一下 JMM：如何解释下面的案例，总感觉实际结果，和自己的理解不一致！！！
 * @Author
 * @Date 2020/11/21 16:29
 * @Version 1.0
 */
public class MyQuestionJMM {

    /**
     *【JMM】
     * 线程操作共享内存数据，会将共享内存数据进行副本拷贝
     * 放到当前线程的工作空间中，当操作完成后再将最后的数据写回到共享内存中
     * @param args
     */
    public static void main(String[] args) {
        Resource resource = new Resource();

        new Thread(() -> {
            // sleep 的目的是，让线程进行共享资源数据的拷贝
            // 此后在线程内操作的 resource 对象，其实是拷贝到线程本地空间的那个变量，而非共享内存中的数据
            // 在调用共享内存对象时，进行对象拷贝；且更新完本地对象的数据后，立马更新共享变量中的数据
            System.out.println(Thread.currentThread().getName() + "\t before" + resource.res);
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            resource.add();
            System.out.println(Thread.currentThread().getName() + "\t after" + resource.res);  //20
        },"A").start();

        new Thread(() -> {
            // sleep 的目的是，让线程进行共享资源数据的拷贝
            System.out.println(Thread.currentThread().getName() + "\t before" + resource.res);
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            resource.add();
            System.out.println(Thread.currentThread().getName() + "\t after" + resource.res);  //20
        },"B").start();

        new Thread(() -> {
            // sleep 的目的是，让线程进行共享资源数据的拷贝
            System.out.println(Thread.currentThread().getName() + "\t before" + resource.res);
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            resource.add();
            System.out.println(Thread.currentThread().getName() + "\t after" + resource.res);  //20
        },"C").start();

        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        System.out.println(Thread.currentThread().getName() + "\t" + resource.res);

    }
}

@Data
class Resource{
    int res = 10;

    public void add(){
        this.res += 10;
    }
}
